#include<iostream>
#include<string>
#include<fstream>
#include<windows.h>
using namespace std;
//自定义定义两个改变字体颜色函数
void SetFontRed() {
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
			FOREGROUND_INTENSITY | FOREGROUND_RED);
}
void SetFontWhite() {
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
			FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN
					| FOREGROUND_BLUE);
}
/*词法分析器*/
#define MAXROW 100//源代码的最大行数
#define MAXTABLE 1000//符号表和常数表最大存储范围
string ReservedWordList[6] = { "begin", "if", "then", "while", "do", "end" }; //关键字表
//声明全局变量
string ScanBuffer[MAXROW]; //扫描缓冲区，定义为字符串数组
struct SymbolTable {
	int code;
	string symbol;
} ST[MAXTABLE]; //符号表
struct ConstantTable {
	int code;
	int constant;
} CT[MAXTABLE]; //常数表
int STi = 0, CTi = 0; //符号表和常数表指示器
struct Word {
	int code;
	string symbol;
	int constant;
} word;
int row = 0, col = 0; //搜索指示器，row指行，col指列
int endrow;
char ch; //搜索指示器指示的当前字符
string strToken; //当前字符串
//声明全局函数
void Input(); //子程序过程，将源代码输入进扫描缓冲区
void GetChar(); //子过程程序，将下一输入字符读到ch中，搜索指示器前移一字符位置
void GetDel(); //子程序过程，检查ch中的字符是否为分隔符。若是，则调用GetChar直至ch中进入一个非分隔符（delimiters->分隔符）
void Concat(); //子程序过程，，将ch中的字符连接到strToken之后
bool IsLetter(); //布尔函数过程，判断ch中的字符是否为字母
bool IsDigit(); //布尔函数构成，判断ch中的字符是否为数字
int Reserve(); //整型函数过程，对strToken中的字符串查找保留字表，若它是一个保留字则返回它的编码，否则返回0值（假定0不是保留字的编码）
void Retract(); //子程序过程，将搜索指示器回调一个字符位置，将ch置为空白字符
int InsertID(); //整型函数过程，将strToken中的标识符插入符号表，返回符号表指针
int InsertConst(); //整型函数过程，将strToken中的常数插入常数表，返回常数表指针
void LexicalAnalyzerProcError(); //子程序过程，词法分析出错，提示错误信息
//定义函数
void Input() {
	int op;
	cout << "请输入数字选择输入格式" << endl;
	cout << "1,键盘输入" << endl << "2,文件输入" << endl;
	cin >> op;
	int i = 0;
	char c; //输入流中的当前字符
	if (op == 1) {
		while ((c = cin.get()) != EOF) {
			ScanBuffer[i].push_back(c);
			if (c == '\n')
				i++;
		}
		endrow = --i;
	} else {
		fstream in;
		in.open("test.txt", ios::in);
		while (in.peek() != EOF) {
			c = in.get();
			ScanBuffer[i].push_back(c);
			if (c == '\n')
				i++;
		}
		endrow = --i;
	}
}
void GetChar() {
	ch = ScanBuffer[row][col];
	col++;
}
void GetDel() {
	while (ch == '\n') {
		row++;
		col = 0;
		GetChar();
	}
	while (ch == ' ' || ch == '\t')
		GetChar();
}
void Concat() {
	strToken.push_back(ch);
}
bool IsLetter() {
	return isalpha(ch);
}
bool IsDigit() {
	return isdigit(ch);
}
int Reserve() {
	int i;
	for (i = 0; i < 6; i++)
		if (ReservedWordList[i] == strToken)
			return i + 1;
	return 10;
}
void Retract() {
	col--;
	ch = '\0';
}
void LexicalAnalyzerProcError() {
	SetFontRed();
	cout << "[Error]" << row << " row" << ',' << col << " col" << endl;
	SetFontWhite();
}
struct Word LexicalAnalyzer() { //结构体函数，向语法分析器返回一个单词的种别码和值
	if (row != endrow || ScanBuffer[row][col] != '\n') {
		int code, value;
		strToken = "";
		GetChar();
		GetDel();
		if (IsLetter()) {
			while (IsLetter() || IsDigit()) {
				Concat();
				GetChar();
			}
			Retract();
			code = Reserve();
			if (code != 10) {
				//value=InsertID(strToken);
				ST[STi].code = word.code = code;
				ST[STi].symbol = word.symbol = strToken;
				STi++;
				return word;
				//cout<<'('<<code<<','<<strToken<<')'<<endl;
				//return (code,value);
			} else {
				ST[STi].code = word.code = code;
				ST[STi].symbol = word.symbol = strToken;
				STi++;
				return word;
				//cout<<'('<<code<<','<<strToken<<')'<<endl;
				//return (code,-);
			}
		} else if (IsDigit()) {
			while (IsDigit()) {
				Concat();
				GetChar();
			}
			Retract();
			//value=InsertConst();
			CT[CTi].code = word.code = 11;
			CT[CTi].constant = word.constant = stoi(strToken);
			CTi++;
			return word;
			//cout<<'('<<11<<','<<strToken<<')'<<endl;
			//return ($INT,value);
		} else if (ch == '+') {
			word.code = 13;
			word.symbol = "+";
			return word;
			//return (13,-);
			//cout<<"(13,+)"<<endl;
		} else if (ch == '-') {
			word.code = 14;
			word.symbol = "-";
			return word;
			//return (14,-);
			//cout<<"(14,-)"<<endl;
		} else if (ch == '*') {
			word.code = 15;
			word.symbol = "*";
			return word;
			//return (15,-);
			//cout<<"(15,*)"<<endl;
		} else if (ch == '/') {
			word.code = 16;
			word.symbol = "/";
			return word;
			//return (16,-);
			//cout<<"(16,/)"<<endl;
		} else if (ch == ':') {
			GetChar();
			if (ch == '=') {
				word.code = 18;
				word.symbol = ":=";
				return word;
				//return (18,-);
				//cout<<"(18,:=)"<<endl;
			} else {
				Retract();
				word.code = 17;
				word.symbol = ":";
				return word;
				//return (17,-);
				//cout<<"(17,:)"<<endl;
			}
		} else if (ch == '<') {
			GetChar();
			if (ch == '>') {
				word.code = 21;
				word.symbol = "<>";
				return word;
				//return (21,-);
				//cout<<"(21,<>)"<<endl;
			} else if (ch == '=') {
				word.code = 22;
				word.symbol = "<=";
				return word;
				//return (22,-);
				//cout<<"(22,<=)"<<endl;
			} else {
				Retract();
				word.code = 20;
				word.symbol = "<";
				return word;
				//return (20,-);
				//cout<<"(20,<)"<<endl;
			}
		} else if (ch == '>') {
			GetChar();
			if (ch == '=') {
				word.code = 24;
				word.symbol = ">=";
				return word;
				//return (24,-);
				//cout<<"(24,>=)"<<endl;
			} else {
				Retract();
				word.code = 23;
				word.symbol = ">";
				return word;
				//return (23,-);
				//cout<<"(23,>)"<<endl;
			}
		} else if (ch == '=') {
			word.code = 25;
			word.symbol = "=";
			return word;
			//return (25,-);
			//cout<<"(25,=)"<<endl;
		} else if (ch == ';') {
			word.code = 26;
			word.symbol = ";";
			return word;
			//return (26,-);
			//cout<<"(26,;)"<<endl;
		} else if (ch == '(') {
			word.code = 27;
			word.symbol = "(";
			return word;
			//return (27,-);
			//cout<<"(27,()"<<endl;
		} else if (ch == ')') {
			word.code = 28;
			word.symbol = ")";
			return word;
			//return (28,-);
			//cout<<"(28,))"<<endl;
		} else if (ch == '#') {
			word.code = 0;
			word.symbol = "#";
			return word;
			//return (0,-);
			//cout<<"(0,#)"<<endl;
		} else
			LexicalAnalyzerProcError();
	}
}

/*词法分析器*/
//////////////////////////////////////////////////////////////////////////////////////////////////
/*语法分析器*/
//声明递归下降分析程序的子程序
void Parser();			//语法分析器总控程序
void ADVANCE();			//把输入串指示器IP指向下一个输入符号
void ParserProcError();			//语法分析器的出错处理子程序
void P();			//非终结符P的分析子程序
void S();			//非终结符S的分析子程序
void S1();			//非终结符S'的分析子程序
void S2();			//非终结符S"的分析子程序
void A();			//非终结符A的分析子程序
void E();			//非终结符E的分析子程序
void E1();			//非终结符E'的分析子程序
void T();			//非终结符T的分析子程序
void T1();			//非终结符T'的分析子程序
void F();			//非终结符F的分析子程序
//声明递归下降分析程序的全局变量
struct Word IP;			//输入串指示器，指示当前扫描器扫描出的单词在表中的地址
struct Word SYM;			//IP当前所指的那个输入符号
//定义函数
void ADVANCE() {
	IP = SYM = LexicalAnalyzer();
}
void ParserProcError(int op) {
	SetFontRed();
	cout << "[Error]" << row << " row" << '\t';
	switch (op) {
	case 1:
		if (SYM.code == 11)
			cout << "expect \'begin\' before " << '\'' << SYM.constant << '\''
					<< endl;
		else
			cout << "expect \'begin\' before " << '\'' << SYM.symbol << '\''
					<< endl;
		break;
	case 2:
		if (SYM.code == 11)
			cout << "expect \'end\' before " << '\'' << SYM.constant << '\''
					<< endl;
		else
			cout << "expect \'end\' before " << '\'' << SYM.symbol << '\''
					<< endl;
		break;
	case 3:
		if (SYM.code == 11)
			cout << "expect \'id\' before " << '\'' << SYM.constant << '\''
					<< endl;
		else
			cout << "expect \'id\' before " << '\'' << SYM.symbol << '\''
					<< endl;
		break;
	case 4:
		if (SYM.code == 11)
			cout << "expect \':=\' before " << '\'' << SYM.constant << '\''
					<< endl;
		else
			cout << "expect \':=\' before " << '\'' << SYM.symbol << '\''
					<< endl;
		break;
	case 5:
		if (SYM.code == 11)
			cout << "expect \'id|num|(\' before " << '\'' << SYM.constant
					<< '\'' << endl;
		else
			cout << "expect \'id|num|(\' before " << '\'' << SYM.symbol << '\''
					<< endl;
		break;
	case 6:
		if (SYM.code == 11)
			cout << "expect \')\' before " << '\'' << SYM.constant << '\''
					<< endl;
		else
			cout << "expect \')\' before " << '\'' << SYM.symbol << '\''
					<< endl;
		break;
	}
	SetFontWhite();
}
/*
 单词符号 种别码 单词符号 种别码
 begin	    1	   :	   17
 if	        2	   :=	   18
 then	    3	   <	   20
 while	    4	   <>	   21
 do	        5	   <=	   22
 end	        6	   >	   23
 id	        10	   >=	   24
 num	        11	   =	   25
 +	        13	   ;	   26
 -	        14	   (	   27
 *	        15	   )	   28
 /	        16	   #	   0
 */
void P() {
	if (SYM.code == 1) {
		ADVANCE();
		S();
		if (SYM.code == 6) {
			ADVANCE();
			if (SYM.code == 0) {
				cout << "语法正确" << endl;
				return;
			}
		} else
			ParserProcError(2);			//没有end
	} else
		ParserProcError(1);			//没有begin
}
void S() {
	S1();
	S2();
}
void S1() {
	A();
}
void S2() {
	if (SYM.code == 26) {
		ADVANCE();
		S1();
		S2();
	}
}
void A() {
	if (SYM.code == 10) {
		ADVANCE();
		if (SYM.code == 18) {
			ADVANCE();
			E();
		} else
			ParserProcError(4);			//当前单词不是:=
	} else
		ParserProcError(3);			//当前单词不是id
}
void E() {
	T();
	E1();
}
void E1() {
	if (SYM.code == 13 || SYM.code == 14) {
		ADVANCE();
		T();
		E1();
	}
}
void T() {
	F();
	T1();
}
void T1() {
	if (SYM.code == 15 || SYM.code == 16) {
		ADVANCE();
		F();
		T1();
	}
}
void F() {
	if (SYM.code == 10)
		ADVANCE();
	else if (SYM.code == 11)
		ADVANCE();
	else if (SYM.code == 27) {
		ADVANCE();
		E();
		if (SYM.code == 28)
			ADVANCE();
		else
			ParserProcError(6);			//')'不匹配
	} else
		ParserProcError(5);			//既不是id，也不是num，更不是'('
}
void Parser() {
	SetFontWhite();
	Input();
	ADVANCE();
	P();
}
int main() {
	Parser();
	return 0;
}
